﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace Helpers
{
    public static class MqHelperExtensions
    {
        /// <summary>
        /// 加载mq配置节,自动注册MqConfig,MqServcieManager,MqChannelManager,以及所有IService实例
        /// </summary>
        public static IServiceCollection AddRabbitMqHelper(this IServiceCollection services, IConfiguration configuration, Action<MqConfig> configare = null)
        {
            //注册配置文件
            services.AddOptions<MqConfig>()
                .Bind(configuration.GetSection(MqConfig.SectionName))
                .ValidateDataAnnotations();
            services.PostConfigure<MqConfig>(x =>
            {
                configare?.Invoke(x);
                MqGlobleConfig.InitDefaultConnection(x);
            });
            services.AddSingleton<MqConfig>(x => x.GetRequiredService<IOptions<MqConfig>>().Value);
            //注册MqServcieManager
            services.AddSingleton<MqServcieManager>();
            //注册MqChannelManager
            services.AddTransient<MqChannelManager>(x => new MqChannelManager(x.GetRequiredService<MqConfig>()));
            //自动注册IService的实例
            AddServices();

            return services;

            void AddServices()
            {
                var allTypes = Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory, "*.dll", SearchOption.AllDirectories)
                    .Select(x => x.Split('\\').Last().Replace(".dll", ""))
                    .Where(x => !Regex.IsMatch(x, @"^(?:Microsoft|System|Helpers|runtime)") && !Regex.IsMatch(x, "resources$"))
                    .Select(x =>
                    {
                        try
                        {
                            return Assembly.Load(new AssemblyName(x));
                        }
                        catch
                        {
                            return null;
                        }
                    })
                    .Where(x => x != null)
                    .SelectMany(x => x.GetTypes())
                    .Where(x => x.IsClass && typeof(IService).IsAssignableFrom(x));
                foreach (var item in allTypes)
                {
                    services.AddSingleton(item);
                }
            }
        }
    }
}
